using System;
using System.Linq.Expressions;
using System.Reflection;

namespace MvvmUtils.Common.Expressions
{
    public class PropertyPathParser : ExpressionVisitor
    {
        private readonly IPropertyPathBuilder _builder;

        public PropertyPathParser(IPropertyPathBuilder builder)
        {
            if (builder == null) throw new ArgumentNullException("builder");

            _builder = builder;
        }

        protected override Expression VisitMember(MemberExpression node)
        {
            switch (node.Expression.NodeType)
            {
                case ExpressionType.MemberAccess:
                    BuildPath(node);
                    break;

                case ExpressionType.Parameter:
                    BuildPath(node);
                    _builder.FinalizePath();
                    break;

                default:
                    if (_builder.IsBuildingPath()) _builder.DiscardPath();
                    break;
            }

            return base.VisitMember(node);
        }

        private void BuildPath(MemberExpression node)
        {
            MemberInfo propertyMember = node.Member;

            if (_builder.IsBuildingPath())
            {
                _builder.AddPrefix(propertyMember);
            }
            else
            {
                _builder.InitializePath();
                _builder.AddSubfix(propertyMember);
            }
        }
    }
}